/*
    TypeScript 函数
 */

/**
 * 函数定义与调用
 */
function test() {   // 函数定义
    console.log("调用函数")
}
test(); // 调用函数

/**
 * 函数返回值 return
 */
// 函数定义
function greet():string { // 返回一个字符串
    return "Hello World"
}
function caller() {
    var msg = greet(); // 调用 greet() 函数
    console.log(msg)
}
// 调用函数
caller();

/**
 * 带参数函数
 */
function add(x: number, y: number): number {
    return x + y;
}
console.log(add(1,2));

/**
 * 可选参数
 * 将 lastName 设置为可选参数
 */
function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}
let result1 = buildName("Bob");  // 正确
// let result2 = buildName("Bob", "Adams", "Sr.");  // 错误，参数太多了
let result3 = buildName("Bob", "Adams");  // 正确

/**
 * 默认参数
 * 参数 rate 设置了默认值为 0.50，调用该函数时如果未传入参数则使用该默认值：
 */
function calculate_discount(price:number,rate:number = 0.50) {
    var discount = price * rate;
    console.log("计算结果: ",discount);
}
calculate_discount(1000);
calculate_discount(1000,0.30);

/**
 * 剩余参数 ES6 ...
 * 剩余参数语法允许我们将一个不确定数量的参数作为一个数组传入。
 */
function buildName2(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName2("Joseph", "Samuel", "Lucas", "MacKinzie");
console.log(employeeName);

function addNumbers(...nums:number[]) {
    var i;
    var sum:number = 0;

    for(i = 0;i<nums.length;i++) {
        sum = sum + nums[i];
    }
    console.log("和为：",sum)
}
addNumbers(1,2,3);
addNumbers(10,10,10,10,10);

/**
 * 匿名函数
 */
var res = function(a:number,b:number) {
    return a*b;
};
console.log(res(12,2));
//匿名函数自调用
(function () {
    var x = "Hello!!";
    console.log(x)
})();

/**
 * 构造函数
 * TypeScript 也支持使用 JavaScript 内置的构造函数 Function() 来定义函数
 */
var myFunction = new Function("a", "b", "return a * b");
var x = myFunction(4, 3);
console.log(x);

/**
 * 递归函数
 */
function factorial(number) {
    if (number <= 0) {         // 停止执行
        return 1;
    } else {
        return (number * factorial(number - 1));     // 调用自身
    }
};
console.log(factorial(6));      // 输出 720

/**
 * Lambda 函数(箭头函数)
 * 箭头函数表达式的语法比函数表达式更短。
 */
var foo = (x:number)=> {
    x = 10 + x
    console.log(x)
};
foo(100);

/**
 * 函数重载
 * 重载是方法名字相同，而参数不同，返回类型可以相同也可以不同，跟返回值类型无关。
 */
function disp(s1:string):void;
function disp(n1:number,s1:string):void;

function disp(x:any,y?:any):void {
    console.log(x);
    console.log(y);
}
disp("abc");
disp(1,"xyz");